#include "Paser.hpp"
#include "../base/Defind.hpp"

#include <optional>
#include <string>
#include <unordered_map>

using namespace DBServer::Database;

// command formet
// "type key value\n"
CommandRequest Paser::paser(std::string&& command)
{
    CommandRequest req;
    CommandPaser::paser(std::move(command), req);
    return req;
}

std::optional<com_func_t> Paser::get_execute_func(std::string& type) {
    auto iter = command_map.find(type);
    if (iter == command_map.end())
    {
        return std::nullopt;
    }
    return iter->second;
}

std::unordered_map<std::string, com_func_t>
Paser::command_map([]() {
    std::unordered_map<std::string, com_func_t> init;

    //Commen
    init["GET"]     = {0, COMMAND_GET};
    init["TTL"]     = {0, TTL};
    init["TYPE"]    = {0, TYPE};
    init["ALIVE"]   = {0, ALIVE};

    // HashObject
    init["HADD"]    = {HASH_TYPE, COMMAND_HADD};
    init["HSIZE"]   = {HASH_TYPE, COMMAND_HSIZE};
    init["HEXIST"]  = {HASH_TYPE, COMMAND_HEXIST};
    init["HREMOVE"] = {HASH_TYPE, COMMAND_HREMOVE};

    // ListObject
    init["LPUSH"]   = {LIST_TYPE, COMMAND_LPUSH};
    init["RPUSH"]   = {LIST_TYPE, COMMAND_RPUSH};
    init["LPOP"]    = {LIST_TYPE, COMMAND_LPOP};
    init["RPOP"]    = {LIST_TYPE, COMMAND_RPOP};
    init["LINDEX"]  = {LIST_TYPE, COMMAND_LINDEX};
    init["LLEN"]    = {LIST_TYPE, COMMAND_LLEN};
    init["LINSERT"] = {LIST_TYPE, COMMAND_LINSERT};
    init["LREMOVE"] = {LIST_TYPE, COMMAND_LREMOVE};
    init["LSET"]    = {LIST_TYPE, COMMAND_LSET};
    init["LTRIM"]   = {LIST_TYPE, COMMAND_LTRIM};

    // SetObject
    init["SADD"]    = {SET_TYPE, COMMAND_SADD};
    init["SSIZE"]   = {SET_TYPE, COMMAND_SSIZE};
    init["SEXIST"]  = {SET_TYPE, COMMAND_SEXIST};
    init["SPOP"]    = {SET_TYPE, COMMAND_SPOP};

    // StringObject
    init["SAPPEND"] = {STRING_TYPE, COMMAND_SAPPEND};
    init["SET"]     = {STRING_TYPE, COMMAND_SET};
    init["SCOMPARE"]= {STRING_TYPE, COMMAND_SCOMPARE};
    init["SCLEAR"]  = {STRING_TYPE, COMMAND_SCLEAR};
    init["SLEN"]    = {STRING_TYPE, COMMAND_SLEN};

    //ZsetObject
    init["ZADD"]    = {ZSET_TYPE, COMMAND_ZADD};
    init["ZLEN"]    = {ZSET_TYPE, COMMAND_ZLEN};
    init["ZCOUNT"]  = {ZSET_TYPE, COMMAND_ZCOUNT};
    init["ZRANK"]   = {ZSET_TYPE, COMMAND_ZCOUNT};
    init["ZSCORE"]  = {ZSET_TYPE, COMMAND_ZRANK};
    init["ZREMOVE"] = {ZSET_TYPE, COMMAND_ZREMOVE};

    return init;
}());
